package com.wzt.consumer.service.impl;

import com.wzt.base.service.impl.BaseServiceImpl;
import com.wzt.base.util.AjaxResponse;
import com.wzt.base.util.MD5Util;
import com.wzt.base.util.SendSmsUtil;
import com.wzt.base.util.VerificationCodeUtil;
import com.wzt.consumer.domain.LoginInfo;
import com.wzt.consumer.dto.LoginByAccountDto;
import com.wzt.consumer.dto.SmsCodeLoginDto;
import com.wzt.consumer.dto.SmsCodeRegisterDto;
import com.wzt.consumer.mapper.LoginInfoMapper;
import com.wzt.consumer.service.ILogininfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wzt
 * @since 2022-09-15
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<LoginInfo> implements ILogininfoService {
    @Autowired
    private LoginInfoMapper loginInfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${smsCode.register.resend-time}")
    private Integer resendTime;

    @Value("${smsCode.register.expire-time}")
    private Integer expireTime;

    @Override
    public AjaxResponse loginByAccount(LoginByAccountDto loginDto) {
        // 1 空校验
        if (StringUtils.isEmpty(loginDto.getUsername())
                || StringUtils.isEmpty(loginDto.getPassword())
                || loginDto.getLoginType() == null) {
            return AjaxResponse.oneResponse().setMessage("请输入相关信息后再登录！");
        }

        // 2 用户登录校验(密码比对和禁用状态)
        // 2.1 验证用户是否存在
        LoginInfo loginInfo = loginInfoMapper.loadByAccount(loginDto);
        if (loginInfo == null) {
            return AjaxResponse.oneResponse().setMessage("用户名或密码不正确！");
        }
        // 2.2 验证用户账号是否可用
        if (loginInfo.getDisable() == -1) {
            return AjaxResponse.oneResponse().setMessage("账户已被冻结，请联系客服！");
        }
        // 2.3 密码比对
        String salt = loginInfo.getSalt();
        String dbPwd = loginInfo.getPassword();
        String inputSecurityPwd = MD5Util.encrypByMd5(loginDto.getPassword() + salt);
        if (!dbPwd.equals(inputSecurityPwd)) {
            return AjaxResponse.oneResponse().setMessage("用户名或密码不正确！");
        }

        /* 3 令牌操作
            (1) 通过UUID生成一个令牌
            (2) 以令牌为key存放用户的基本信息到Redis中
            (3) 返回令牌和用户信息
         */
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, loginInfo, 30, TimeUnit.MINUTES);
        // 以Map的形式返回结果（包含令牌和用户登录信息）
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);

        // 先将盐值和密码置为空在返回以保安全
        loginInfo.setSalt(null);
        loginInfo.setPassword(null);
        result.put("loginInfo", loginInfo);
        return AjaxResponse.oneResponse().setData(result);
    }

    /**
     * 发送登录短信验证码
     * @param phone
     * @return
     */
    @Override
    public AjaxResponse loginBySms(String phone) {
        //1.2 判断手机号是否已经被注册
        LoginInfo logininfo = loginInfoMapper.loadUserByMobile(phone);
        if (logininfo == null) {
            return AjaxResponse.oneResponse().setSuccess(false).setMessage("该手机号还未注册或未绑定您的账号！");
        }

        //2 判断原来的验证码是否存在
        String key = "register_sms_code_" + phone;

        String smsCodeOfRedis = (String) redisTemplate.opsForValue()
                .get(key);
        String code = "";
        if (StringUtils.isEmpty(smsCodeOfRedis)) {
            //2.1 如果不存在就产生新的
            code = VerificationCodeUtil.getRandomString(6);
        } else {
            //2.2 如果存在，判断是否已过重发时间，如果没有过报错，过了直接原来的
            code = smsCodeOfRedis.split(":")[0];
            String time = smsCodeOfRedis.split(":")[1];
            if (System.currentTimeMillis() - new Date(Long.valueOf(time)).getTime() <= 60 * 1000 * resendTime) {
                return AjaxResponse.oneResponse().setSuccess(false).setMessage("非法请求，请勿乱搞！");
            }
        }

        //3 记录验证码到redis
        redisTemplate.opsForValue().set(key, code + ":" + System.currentTimeMillis(), expireTime, TimeUnit.MINUTES);

        String content = String.format("你的验证码为%s,请在%s分钟之内使用！", code, expireTime);
        SendSmsUtil.sendSms(phone, content);
        System.out.println("已经成功发送了一条短信,内容为" + content);
        return AjaxResponse.oneResponse();
    }

    /**
     * 验证登录短信验证码
     * @param smsCodeDto
     * @return
     */
    @Override
    public AjaxResponse smsValidate(SmsCodeLoginDto smsCodeDto) {
        String phone = smsCodeDto.getPhone();
        String smsCode = smsCodeDto.getSmsCode();
        // 注册短信验证码的key
        String key = "register_sms_code_" + phone;

        // 短信验证码判断
        String smsCodeOfRedis = (String) redisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(smsCodeOfRedis) || !smsCodeOfRedis.split(":")[0].equals(smsCode)) {
            return AjaxResponse.oneResponse().setSuccess(false).setMessage("短信验证码过期或者错误！");
        }
        return AjaxResponse.oneResponse();
    }
}
